package xrc.service.impl;

import com.alibaba.fastjson.JSONObject;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import xrc.contract.MaskVoteContract;

import xrc.domain.ECPoint;

import javax.annotation.PostConstruct;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;

@Component
public class MaskVoteImpl {

    int t = 1; //门限值

    static Logger logger = LoggerFactory.getLogger(MaskVoteImpl.class);
    private BcosSDK bcosSDK;
    public Client client;
    private CryptoKeyPair cryptoKeyPair;
    JSONObject object = new JSONObject();

    private MaskVoteContract contract;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @PostConstruct
    public void initialize() throws Exception {
        @SuppressWarnings("resource")
        ApplicationContext context =
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        bcosSDK = context.getBean(BcosSDK.class);
        client = bcosSDK.getClient(1);
        cryptoKeyPair = client.getCryptoSuite().createKeyPair();
        client.getCryptoSuite().setCryptoKeyPair(cryptoKeyPair);
        logger.debug("create client for group1, account address is " + cryptoKeyPair.getAddress());

        String contractAddress = loadMaskVoteAddr();
        contract = MaskVoteContract.load(contractAddress, client, cryptoKeyPair);
    }

    public void deployAssetAndRecordAddr() {

        try {
            MaskVoteContract contract = MaskVoteContract.deploy(client, cryptoKeyPair);
            System.out.println(
                    " deploy MaskVote success, contract address is " + contract.getContractAddress());

            recordMaskVoteAddr(contract.getContractAddress());

        } catch (Exception e) {
            // TODO Auto-generated catch block
            // e.printStackTrace();
            System.out.println(" deploy MaskVote contract failed, error message is  " + e.getMessage());
        }
    }

    public void recordMaskVoteAddr(String address) throws FileNotFoundException, IOException {
        Properties prop = new Properties();
        prop.setProperty("address", address);
        final Resource contractResource = new ClassPathResource("contract.properties");
        FileOutputStream fileOutputStream = new FileOutputStream(contractResource.getFile());
        prop.store(fileOutputStream, "contract address");

    }

    public String loadMaskVoteAddr() throws Exception {
        // load Asset contact address from contract.properties
        Properties prop = new Properties();
        final Resource contractResource = new ClassPathResource("contract.properties");
        prop.load(contractResource.getInputStream());

        String contractAddress = prop.getProperty("address");
        if (contractAddress == null || contractAddress.trim().equals("")) {
            throw new Exception(" load MaskVote contract address failed, please deploy it first. ");
        }
        logger.info(" load MaskVote address from contract.properties, address is {}", contractAddress);
        return contractAddress;
    }

    public MaskVoteContract Client() throws Exception {
        return contract;
    }


    public TransactionReceipt publish(String id, String voteId) throws Exception {
        System.out.println("contract = " + contract);
        TransactionReceipt publish = contract.publish(id, voteId);
        return publish;
    }

    public TransactionReceipt addA(String id, List<String> AList) throws Exception {

        TransactionReceipt transactionReceipt = contract.addA(id, AList);
        return transactionReceipt;
    }

    public ECPoint getA(String voterId) throws Exception {

        List a1 = contract.getA(voterId);
        String A0 = a1.get(0).toString();
        String[] str = A0.split(",");
        BigInteger X = new BigInteger(str[0],16);
        BigInteger Y = new BigInteger(str[1],16);
        ECPoint ecPoint = new ECPoint(X, Y);
        return ecPoint;
    }

    public TransactionReceipt addY(String voteId, List<String> YList) throws Exception {

        TransactionReceipt transactionReceipt = contract.addY(voteId, YList);
        return transactionReceipt;
    }

    public ECPoint getY(String voteId) throws Exception {

        List YList = contract.getY(voteId);
        String s = YList.toString();
        String substring = s.substring(1, s.length() - 1);
        System.out.println(substring);
        String[] str = substring.split(",");
        BigInteger o1 = new BigInteger(str[0],16);
        BigInteger o2 = new BigInteger(str[1],16);
        ECPoint Y = new ECPoint(o1, o2);
        System.out.println("获得的联合公钥为 = " + Y);
        return Y;
    }

    public List getSecVote(String loginId, String voteId) throws Exception {

        List secVote = contract.getSecVote(loginId, voteId);
        return secVote;
    }

    public TransactionReceipt addMixedVote(String voteId, List<String> mixedVote) throws Exception {

        TransactionReceipt transactionReceipt = contract.addMixedVote(voteId, mixedVote);
        return transactionReceipt;

    }

    public ECPoint getE0(String voteId) throws Exception {

        List mixedVote = contract.getMixedVote(voteId);

        String allMixed = (String) mixedVote.get(0);
        System.out.println("allMixed = " + allMixed);
        String[] mixed = allMixed.split(",");

        BigInteger x = new BigInteger(mixed[0],16);
        BigInteger y = new BigInteger(mixed[1],16);
        ECPoint E0 = new ECPoint(x, y);
        return E0;
    }

    public ECPoint getE1(String voteId) throws Exception {

        List mixedVote = contract.getMixedVote(voteId);

        System.out.println("mixedVote.get(1) = " + mixedVote.get(1));
        String allMixed = mixedVote.get(1).toString();

        System.out.println("allMixed = " + allMixed);
        String[] mixed = allMixed.split(",");

        BigInteger x = new BigInteger(mixed[0],16);
        BigInteger y = new BigInteger(mixed[1],16);
        ECPoint E1 = new ECPoint(x, y);
        return E1;
    }

    public TransactionReceipt addg_R(String loginId, String voteId, List<String> GR) throws Exception {

        TransactionReceipt transactionReceipt = contract.addg_R(loginId, voteId, GR);
        return transactionReceipt;
    }

    public ECPoint getg_R(String id, String voteId) throws Exception {

        List getGR = contract.getg_R(id, voteId);
        System.out.println("得到的GR = " + getGR);
        System.out.println("getGR.get(0) = " + getGR.get(0));

        String GR = getGR.get(0).toString();
        String[] str = GR.split(",");
        BigInteger X = new BigInteger(str[0],16);
        BigInteger Y = new BigInteger(str[1],16);
        ECPoint GRi = new ECPoint(X, Y);
        System.out.println("GRi = " + GRi);
        return GRi;
    }

    public TransactionReceipt addF(String i, String sqlId, List<String> SList) throws Exception {

        TransactionReceipt transactionReceipt = contract.addF(i, sqlId, SList);
        return transactionReceipt;
    }

    public TransactionReceipt addC(String id, List<String> CList) throws Exception {

        TransactionReceipt transactionReceipt = contract.addC(id, CList);
        return transactionReceipt;
    }

    public ECPoint[] verifyS(String verifyId) throws Exception {

        /*List f = contract.getF(loginId, verifyId);

        BigInteger[] s = new BigInteger[2];
        BigInteger s_ji0 = new BigInteger((String) f.get(0));
        System.out.println("S0 = " + s_ji0);
        BigInteger s_ji1 = new BigInteger((String) f.get(1));
        s[0] = s_ji0;
        s[1] = s_ji1;*/
        List c = contract.getC(verifyId);
        for (Object o : c) {
            System.out.println("用户的C值为 = " + o);
        }
        String[] getCList = new String[t + 1];

        for (int j = 0; j < c.size(); j++) {
            getCList[j] = String.valueOf(c.get(j));
            System.out.println(" getCList[j] = " + getCList[j]);
        }

        ECPoint[] CList = new ECPoint[t + 1];
        System.out.println("CList.length = " + CList.length);
        for (int t = 0; t < CList.length; t++) {

            System.out.println("当前轮数t = " + t);
            String C = getCList[t];
            System.out.println("getCList[t] = " + getCList[t]);

            String[] strs = C.split(",");
            BigInteger X = new BigInteger(strs[0],16);
            BigInteger Y = new BigInteger(strs[1],16);
            ECPoint ecPoint = new ECPoint(X, Y);
            CList[t] = ecPoint;
        }
        for (ECPoint ecPoint : CList) {
            System.out.println("ecPoint = " + ecPoint);
        }

        return CList;
    }

    public ECPoint[] verifyA(String verifyId) throws Exception {

        List a = contract.getA(verifyId);
        System.out.println("被验证的用户A值为 = " + a);
        String[] getAList = new String[t + 1];
        for (int j = 0; j < a.size(); j++) {
            getAList[j] = a.get(j).toString();
        }

        ECPoint[] AList = new ECPoint[t + 1];
        for (int t = 0; t < AList.length; t++) {
            String A = getAList[t];
            String[] str = A.split(",");
            BigInteger X = new BigInteger(str[0],16);
            BigInteger Y = new BigInteger(str[1],16);
            ECPoint ecPoint = new ECPoint(X, Y);
            AList[t] = ecPoint;
        }
        return AList;
    }

    public BigInteger[] s(String loginId, String verifyId) throws Exception {

        List f = contract.getF(loginId, verifyId);
        System.out.println("loginId = " + loginId);
        System.out.println("verifyId = " + verifyId);
        System.out.println("秘密值为 = " + f);
        System.out.println("f.size() = " + f.size());

        BigInteger[] s = new BigInteger[2];
        System.out.println("f.get(0) = " + f.get(0));
        BigInteger s_ji0 = new BigInteger((String) f.get(0));
        BigInteger s_ji1 = new BigInteger((String) f.get(1));
        System.out.println("s_ji0 = " + s_ji0);
        System.out.println("s_ji1 = " + s_ji1);
        s[0] = s_ji0;
        s[1] = s_ji1;
        return s;
    }

    public BigInteger s_ji0(String loginId, String verifyId) throws Exception {

        List f = contract.getF(loginId, verifyId);

        BigInteger s_ji0 = new BigInteger((String) f.get(0));
        return s_ji0;
    }

    public void addVerifyFlag(String loginId, String verifyId) throws Exception {

        contract.addVerifyFlag(loginId, verifyId);
    }

    public TransactionReceipt addSecVote(String loginId, String voteId, List<String> enVoteList) throws Exception {

        TransactionReceipt transactionReceipt = contract.addSecVote(loginId, voteId, enVoteList);
        return transactionReceipt;
    }

    public void addVoteFlag(String loginId, String voteId) throws Exception {

        contract.addVerifyFlag(loginId, voteId);
    }


    public void addPrecount(String loginId, String voteId) throws Exception {

        contract.addPrecount(loginId, voteId);
    }

    public void voteFlag(String id, String voteId){
        contract.vote(id, voteId);
    }


    public Connection connection() throws ClassNotFoundException, SQLException {

        String driverName = "com.mysql.cj.jdbc.Driver";
        String dbURL = "jdbc:mysql://localhost:3306/db01";
        String userName = "root";
        String userPwd = "123456";

        Class.forName(driverName);
        Connection connection = DriverManager.getConnection(dbURL, userName, userPwd);

        return connection;

    }


}
